main.mk 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. # openMSX Build System
  2. # ====================
  3. #
  4. # This is the home made build system for openMSX, adapted for the openMSX
  5. # debugger.
  6. #
  7. # Used a lot of ideas from Peter Miller's excellent paper
  8. # "Recursive Make Considered Harmful".
  9. # http://www.tip.net.au/~millerp/rmch/recu-make-cons-harm.html
  10. #
  11. # TODO: Rename OPENMSX_SUBSET to SUBSET?
  12. # Python Interpreter
  13. # ==================
  14. # We need Python from the 2.x series, version 2.5 or higher.
  15. # Usually this executable is available as just "python", but on some systems
  16. # you might have to be more specific, for example "python2" or "python2.6".
  17. # Or if the Python interpreter is not in the search path, you can specify its
  18. # full path.
  19. PYTHON?=python
  20. # Logical Targets
  21. # ===============
  22. # Logical targets which require dependency files.
  23. #DEPEND_TARGETS:=all app default install run bindist
  24. DEPEND_TARGETS:=all app default
  25. # Logical targets which do not require dependency files.
  26. #NODEPEND_TARGETS:=clean config probe dist
  27. NODEPEND_TARGETS:=clean dist
  28. # Mark all logical targets as such.
  29. .PHONY: $(DEPEND_TARGETS) $(NODEPEND_TARGETS)
  30. # Default target; make sure this is always the first target in this Makefile.
  31. MAKECMDGOALS?=default
  32. default: all
  33. # Base Directories
  34. # ================
  35. # All created files will be inside this directory.
  36. BUILD_BASE:=derived
  37. # All global Makefiles are inside this directory.
  38. MAKE_PATH:=build
  39. # Platforms
  40. # =========
  41. ifeq ($(origin OPENMSX_TARGET_OS),environment)
  42. # Do not perform autodetection if platform was specified by the user.
  43. else # OPENMSX_TARGET_OS not from environment
  44. DETECTSYS_PATH:=$(BUILD_BASE)/detectsys
  45. DETECTSYS_MAKE:=$(DETECTSYS_PATH)/detectsys.mk
  46. DETECTSYS_SCRIPT:=$(MAKE_PATH)/detectsys.py
  47. -include $(DETECTSYS_MAKE)
  48. $(DETECTSYS_MAKE): $(DETECTSYS_SCRIPT)
  49. @echo "Autodetecting native system:"
  50. @mkdir -p $(@D)
  51. @$(PYTHON) $< > $@
  52. endif # OPENMSX_TARGET_OS
  53. PLATFORM:=
  54. ifneq ($(origin OPENMSX_TARGET_OS),undefined)
  55. PLATFORM:=$(OPENMSX_TARGET_OS)
  56. endif
  57. # Ignore rest of Makefile if autodetection was not performed yet.
  58. # Note that the include above will force a reload of the Makefile.
  59. ifneq ($(PLATFORM),)
  60. # Load OS specific settings.
  61. #$(call DEFCHECK,OPENMSX_TARGET_OS)
  62. #include $(MAKE_PATH)/platform-$(OPENMSX_TARGET_OS).mk
  63. # Check that all expected variables were defined by OS specific Makefile:
  64. # - executable file name extension
  65. #$(call DEFCHECK,EXEEXT)
  66. # - platform supports symlinks?
  67. #$(call BOOLCHECK,USE_SYMLINK)
  68. # Paths
  69. # =====
  70. #BUILD_PATH:=$(BUILD_BASE)/$(PLATFORM)-$(OPENMSX_FLAVOUR)
  71. BUILD_PATH:=$(BUILD_BASE)
  72. GEN_SRC_PATH:=$(BUILD_PATH)/src
  73. SOURCES_PATH:=src
  74. RESOURCES_PATH:=resources
  75. ifeq ($(OPENMSX_TARGET_OS),darwin)
  76. # Note: Make cannot deal with spaces inside paths: it will even see BINARY_FULL
  77. # as two files instead of one. Therefore, we use an underscore during
  78. # development and we'll have to rename the app folder for the release
  79. # versions.
  80. APP_SUPPORT_PATH:=build/package-darwin
  81. APP_PATH:=$(BUILD_PATH)/openMSX_Debugger.app
  82. APP_PLIST:=$(APP_PATH)/Contents/Info.plist
  83. APP_ICON:=$(APP_PATH)/Contents/Resources/debugger-logo.icns
  84. APP_RESOURCES:=$(APP_ICON)
  85. BINARY_PATH:=$(APP_PATH)/Contents/MacOS
  86. PKGINFO_FULL:=$(APP_PATH)/Contents/PkgInfo
  87. else
  88. BINARY_PATH:=$(BUILD_PATH)/bin
  89. endif
  90. #BINARY_FILE:=openmsx-debugger$(EXEEXT)
  91. BINARY_FILE:=openmsx-debugger
  92. BINARY_FULL:=$(BINARY_PATH)/$(BINARY_FILE)
  93. VERSION_SCRIPT:=build/version2code.py
  94. VERSION_HEADER:=$(BUILD_PATH)/config/Version.ii
  95. GENERATED_HEADERS:=$(VERSION_HEADER)
  96. # Filesets
  97. # ========
  98. # If there will be more resource files, introduce a new category in node.mk.
  99. RESOURCES_FULL:=$(RESOURCES_PATH)/resources.qrc
  100. # Force evaluation upon assignment.
  101. SOURCES_FULL:=
  102. HEADERS_FULL:=
  103. MOC_HDR_FULL:=
  104. UI_FULL:=
  105. # Include root node.
  106. CURDIR:=
  107. include node.mk
  108. # Remove "./" in front of file names.
  109. # It can cause trouble because Make removes it automatically in rules.
  110. SOURCES_FULL:=$(SOURCES_FULL:./%=%)
  111. HEADERS_FULL:=$(HEADERS_FULL:./%=%)
  112. MOC_HDR_FULL:=$(MOC_HDR_FULL:./%=%)
  113. UI_FULL:=$(UI_FULL:./%=%)
  114. # Apply subset to sources list.
  115. SOURCES_FULL:=$(filter $(SOURCES_PATH)/$(OPENMSX_SUBSET)%,$(SOURCES_FULL))
  116. ifeq ($(SOURCES_FULL),)
  117. $(error Sources list empty $(if \
  118. $(OPENMSX_SUBSET),after applying subset "$(OPENMSX_SUBSET)*"))
  119. endif
  120. # Sanity check: only .cpp files are allowed in sources list,
  121. # because we don't have any way to build other sources.
  122. NON_CPP_SOURCES:=$(filter-out %.cpp,$(SOURCES_FULL))
  123. ifneq ($(NON_CPP_SOURCES),)
  124. $(error The following sources files do not have a .cpp extension: \
  125. $(NON_CPP_SOURCES))
  126. endif
  127. MOC_SRC_FULL:=$(patsubst \
  128. $(SOURCES_PATH)/%.h,$(GEN_SRC_PATH)/moc_%.cpp,$(MOC_HDR_FULL) \
  129. )
  130. RES_SRC_FULL:=$(patsubst \
  131. $(RESOURCES_PATH)/%.qrc,$(GEN_SRC_PATH)/qrc_%.cpp,$(RESOURCES_FULL) \
  132. )
  133. UI_HDR_FULL:=$(patsubst \
  134. $(SOURCES_PATH)/%.ui,$(GEN_SRC_PATH)/ui_%.h,$(UI_FULL) \
  135. )
  136. GEN_SRC_FULL:=$(MOC_SRC_FULL) $(RES_SRC_FULL)
  137. SOURCES:=$(SOURCES_FULL:$(SOURCES_PATH)/%.cpp=%)
  138. GEN_SRC:=$(GEN_SRC_FULL:$(GEN_SRC_PATH)/%.cpp=%)
  139. HEADERS:=$(HEADERS_FULL:$(SOURCES_PATH)/%=%)
  140. DEPEND_PATH:=$(BUILD_PATH)/dep
  141. DEPEND_FULL:=$(addsuffix .d,$(addprefix $(DEPEND_PATH)/,$(SOURCES)))
  142. DEPEND_FULL+=$(addsuffix .d,$(addprefix $(DEPEND_PATH)/,$(GEN_SRC)))
  143. OBJECTS_PATH:=$(BUILD_PATH)/obj
  144. OBJECTS_FULL:=$(addsuffix .o,$(addprefix $(OBJECTS_PATH)/,$(SOURCES)))
  145. GEN_OBJ_FULL:=$(addsuffix .o,$(addprefix $(OBJECTS_PATH)/,$(GEN_SRC)))
  146. ifeq ($(OPENMSX_TARGET_OS),mingw32)
  147. RESOURCE_SRC:=$(RESOURCES_PATH)/openmsx-debugger.rc
  148. RESOURCE_OBJ:=$(OBJECTS_PATH)/resources.o
  149. RESOURCE_SCRIPT:=build/win_resource.py
  150. RESOURCE_HEADER:=$(BUILD_PATH)/config/resource-info.h
  151. else
  152. RESOURCE_OBJ:=
  153. endif
  154. # Build Rules
  155. # ===========
  156. # Include dependency files.
  157. ifneq ($(filter $(DEPEND_TARGETS),$(MAKECMDGOALS)),)
  158. -include $(DEPEND_FULL)
  159. endif
  160. # Clean up build tree of current flavour.
  161. # We don't have flavours (yet?), so clean up everything except "detectsys".
  162. clean:
  163. @echo "Cleaning up..."
  164. @rm -rf $(OBJECTS_PATH)
  165. @rm -rf $(DEPEND_PATH)
  166. @rm -rf $(GEN_SRC_PATH)
  167. ifeq ($(OPENMSX_TARGET_OS),darwin)
  168. @rm -rf $(APP_PATH)
  169. else
  170. @rm -rf $(BINARY_PATH)
  171. endif
  172. # Generate version header.
  173. .PHONY: forceversionextraction
  174. forceversionextraction:
  175. $(VERSION_HEADER): forceversionextraction
  176. @$(PYTHON) $(VERSION_SCRIPT) $@
  177. # Default target.
  178. ifeq ($(OPENMSX_TARGET_OS),darwin)
  179. all: app
  180. else
  181. all: $(BINARY_FULL)
  182. endif
  183. ifeq ($(QMAKE),)
  184. QMAKE:=qmake
  185. QT_VERSION:=$(shell $(QMAKE) -query QT_VERSION 2> /dev/null)
  186. ifeq ($(QT_VERSION),)
  187. QMAKE:=/usr/local/opt/qt5/bin/qmake
  188. QT_VERSION:=$(shell $(QMAKE) -query QT_VERSION)
  189. endif
  190. else
  191. QT_VERSION:=$(shell $(QMAKE) -query QT_VERSION)
  192. endif
  193. ifeq ($(QT_VERSION),)
  194. $(error qmake not found, please install and/or pass QMAKE)
  195. else ifeq ($(filter 5.%,$(QT_VERSION)),)
  196. $(error Qt version $(QT_VERSION) found; please pass QMAKE pointing to Qt 5.x instead)
  197. endif
  198. QT_INSTALL_HEADERS:=$(shell $(QMAKE) -query QT_INSTALL_HEADERS)
  199. QT_INSTALL_LIBS:=$(shell $(QMAKE) -query QT_INSTALL_LIBS)
  200. QT_INSTALL_BINS:=$(shell $(QMAKE) -query QT_INSTALL_BINS)
  201. # On MingW32 you get backslashes from qmake -query, which we don't want:
  202. ifeq ($(OPENMSX_TARGET_OS),mingw32)
  203. QT_INSTALL_HEADERS:=$(subst \,/,$(QT_INSTALL_HEADERS))
  204. QT_INSTALL_LIBS:=$(subst \,/,$(QT_INSTALL_LIBS))
  205. QT_INSTALL_BINS:=$(subst \,/,$(QT_INSTALL_BINS))
  206. endif
  207. QT_COMPONENTS:=Core Widgets Gui Network Xml
  208. QT_HEADER_DIRS:=$(addprefix $(QT_INSTALL_HEADERS)/Qt,$(QT_COMPONENTS))
  209. QT_HEADER_DIRS+=$(QT_INSTALL_HEADERS)
  210. ifeq ($(OPENMSX_TARGET_OS),darwin)
  211. QT_HEADER_DIRS+=$(patsubst %,/Library/Frameworks/Qt%.framework/Headers,$(QT_COMPONENTS))
  212. endif
  213. CXX?=c++
  214. WINDRES?=windres
  215. CXXFLAGS:= -g -fPIC
  216. INCLUDE_INTERNAL:=$(sort $(foreach header,$(HEADERS_FULL),$(patsubst %/,%,$(dir $(header)))))
  217. INCLUDE_INTERNAL+=$(BUILD_PATH)/config
  218. COMPILE_FLAGS:=$(addprefix -I,$(QT_HEADER_DIRS) $(INCLUDE_INTERNAL) $(GEN_SRC_PATH))
  219. # Enable C++11
  220. COMPILE_FLAGS+=-std=c++11
  221. ifeq ($(OPENMSX_TARGET_OS),darwin)
  222. LINK_FLAGS:=-F$(QT_INSTALL_LIBS) $(addprefix -framework Qt,$(QT_COMPONENTS))
  223. OSX_VER:=10.7
  224. COMPILE_FLAGS+=-mmacosx-version-min=$(OSX_VER) -stdlib=libc++
  225. LINK_FLAGS+=-mmacosx-version-min=$(OSX_VER) -stdlib=libc++
  226. else
  227. COMPILE_ENV:=
  228. LINK_ENV:=
  229. ifeq ($(OPENMSX_TARGET_OS),mingw32)
  230. COMPILE_FLAGS+=-static-libgcc -static-libstdc++
  231. LINK_FLAGS:=-Wl,-rpath,$(QT_INSTALL_BINS) -L$(QT_INSTALL_BINS) $(addprefix -lQt5,$(QT_COMPONENTS)) -lws2_32 -lsecur32 -mwindows -static-libgcc -static-libstdc++
  232. else
  233. LINK_FLAGS:=-Wl,-rpath,$(QT_INSTALL_LIBS) -L$(QT_INSTALL_LIBS) $(addprefix -lQt5,$(QT_COMPONENTS))
  234. endif
  235. endif
  236. DEPEND_FLAGS:=
  237. # GCC flags:
  238. # (these should be omitted if we ever want to support other compilers)
  239. # Generic compilation flags.
  240. CXXFLAGS+=-pipe
  241. # Stricter warning and error reporting.
  242. CXXFLAGS+=-Wall
  243. # Empty definition of used headers, so header removal doesn't break things.
  244. DEPEND_FLAGS+=-MP
  245. # Generate Meta Object Compiler sources.
  246. $(MOC_SRC_FULL): $(GEN_SRC_PATH)/moc_%.cpp: $(SOURCES_PATH)/%.h
  247. @echo "Generating $(@F)..."
  248. @mkdir -p $(@D)
  249. @$(QT_INSTALL_BINS)/moc -o $@ $<
  250. # Generate resource source.
  251. $(RES_SRC_FULL): $(GEN_SRC_PATH)/qrc_%.cpp: $(RESOURCES_PATH)/%.qrc
  252. @echo "Generating $(@F)..."
  253. @mkdir -p $(@D)
  254. @$(QT_INSTALL_BINS)/rcc -name $(<:$(RESOURCES_PATH)/%.qrc=%) $< -o $@
  255. # Generate ui files.
  256. $(UI_HDR_FULL): $(GEN_SRC_PATH)/ui_%.h: $(SOURCES_PATH)/%.ui
  257. @echo "Generating $(@F)..."
  258. @mkdir -p $(@D)
  259. @$(QT_INSTALL_BINS)/uic -o $@ $<
  260. # This is a workaround for the lack of order-only dependencies in GNU Make
  261. # versions before than 3.80 (for example Mac OS X 10.3 still ships with 3.79).
  262. # It creates a dummy file, which is never modified after its initial creation.
  263. # If a rule that produces a file does not modify that file, Make considers the
  264. # target to be up-to-date. That way, the targets "ui-dummy-file" depends on
  265. # will always be checked before compilation, but they will not cause all object
  266. # files to be considered outdated.
  267. GEN_DUMMY_FILE:=$(GEN_SRC_PATH)/dummy-file
  268. $(GEN_DUMMY_FILE): $(UI_HDR_FULL) $(GENERATED_HEADERS)
  269. @test -e $@ || touch $@
  270. # Compile and generate dependency files in one go.
  271. SRC_DEPEND_SUBST=$(patsubst $(SOURCES_PATH)/%.cpp,$(DEPEND_PATH)/%.d,$<)
  272. GEN_DEPEND_SUBST=$(patsubst $(GEN_SRC_PATH)/%.cpp,$(DEPEND_PATH)/%.d,$<)
  273. $(OBJECTS_FULL): $(GEN_DUMMY_FILE)
  274. $(OBJECTS_FULL): $(OBJECTS_PATH)/%.o: $(SOURCES_PATH)/%.cpp $(DEPEND_PATH)/%.d
  275. @echo "Compiling $(patsubst $(SOURCES_PATH)/%,%,$<)..."
  276. @mkdir -p $(@D)
  277. @mkdir -p $(patsubst $(OBJECTS_PATH)%,$(DEPEND_PATH)%,$(@D))
  278. @$(COMPILE_ENV) $(CXX) \
  279. $(DEPEND_FLAGS) -MMD -MF $(SRC_DEPEND_SUBST) \
  280. -o $@ $(CXXFLAGS) $(COMPILE_FLAGS) -c $<
  281. @touch $@ # Force .o file to be newer than .d file.
  282. $(GEN_OBJ_FULL): $(OBJECTS_PATH)/%.o: $(GEN_SRC_PATH)/%.cpp $(DEPEND_PATH)/%.d
  283. @echo "Compiling $(patsubst $(GEN_SRC_PATH)/%,%,$<)..."
  284. @mkdir -p $(@D)
  285. @mkdir -p $(patsubst $(OBJECTS_PATH)%,$(DEPEND_PATH)%,$(@D))
  286. @$(COMPILE_ENV) $(CXX) \
  287. $(DEPEND_FLAGS) -MMD -MF $(GEN_DEPEND_SUBST) \
  288. -o $@ $(CXXFLAGS) $(COMPILE_FLAGS) -c $<
  289. @touch $@ # Force .o file to be newer than .d file.
  290. # Generate dependencies that do not exist yet.
  291. # This is only in case some .d files have been deleted;
  292. # in normal operation this rule is never triggered.
  293. $(DEPEND_FULL):
  294. # Windows resources that are added to the executable.
  295. ifeq ($(OPENMSX_TARGET_OS),mingw32)
  296. $(RESOURCE_HEADER): forceversionextraction
  297. @$(PYTHON) $(RESOURCE_SCRIPT) $@
  298. $(RESOURCE_OBJ): $(RESOURCE_SRC) $(RESOURCE_HEADER)
  299. @echo "Compiling resources..."
  300. @mkdir -p $(@D)
  301. @$(WINDRES) $(addprefix --include-dir=,$(^D)) -o $@ -i $<
  302. endif
  303. # Link executable.
  304. $(BINARY_FULL): $(OBJECTS_FULL) $(GEN_OBJ_FULL) $(RESOURCE_OBJ)
  305. ifeq ($(OPENMSX_SUBSET),)
  306. @echo "Linking $(@F)..."
  307. @mkdir -p $(@D)
  308. @$(LINK_ENV) $(CXX) -o $@ $(CXXFLAGS) $^ $(LINK_FLAGS)
  309. else
  310. @echo "Not linking $(notdir $@) because only a subset was built."
  311. endif
  312. # Application folder.
  313. ifeq ($(OPENMSX_TARGET_OS),darwin)
  314. app: $(BINARY_FULL) $(PKGINFO_FULL) $(APP_PLIST) $(APP_RESOURCES)
  315. $(PKGINFO_FULL):
  316. @echo "Generating $(@F)..."
  317. @mkdir -p $(@D)
  318. @echo "APPLoMXD" > $@
  319. $(APP_PLIST): $(APP_PATH)/Contents/%: $(APP_SUPPORT_PATH)/%
  320. @echo "Generating $(@F)..."
  321. @mkdir -p $(@D)
  322. @sed -e 's/%ICON%/$(notdir $(APP_ICON))/' \
  323. -e 's/%VERSION%/$(PACKAGE_DETAILED_VERSION)/' < $< > $@
  324. $(APP_RESOURCES): $(APP_PATH)/Contents/Resources/%: $(APP_SUPPORT_PATH)/%
  325. @echo "Copying $(@F)..."
  326. @mkdir -p $(@D)
  327. @cp $< $@
  328. endif
  329. # Source Packaging
  330. # ================
  331. dist:
  332. @$(PYTHON) build/gitdist.py
  333. endif # PLATFORM