diff --git a/CMakeLists.txt b/CMakeLists.txt index a11c0c4427..0f00af0f61 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,10 +25,14 @@ target_link_libraries(bfVFS PRIVATE 7z) # ja2export utility add_subdirectory("ext/export/src") -# internal libraries that are Good +# static libraries whose source files, header files or header files included +# by header files do not rely on Applications or Languages preprocessor definitions, +# and therefore only need to be compiled once. Good. add_subdirectory(Lua) -# internal libraries that live in Preprocessor Hell, because they are Bad +# static libraries whose source files, header files or header files included +# by header files rely on Application and Language preprocessor definitions, and +# therefore need to be compiled multiple times. Very Bad. add_subdirectory(TileEngine) add_subdirectory(TacticalAI) add_subdirectory(Utils) @@ -110,6 +114,7 @@ bfVFS "ws2_32.lib" ) +# simple function to validate Languages and Application choices include(cmake/ValidateOptions.cmake) set(ValidLanguages CHINESE DUTCH ENGLISH FRENCH GERMAN ITALIAN POLISH RUSSIAN) @@ -119,42 +124,48 @@ set(ValidApplications JA2 JA2MAPEDITOR JA2UB JA2UBMAPEDITOR) ValidateOptions("${ValidApplications}" "Applications" "${Applications}" "ApplicationTargets") +# preprocessor definitions for Debug build, per the legacy MSBuild +set(debugFlags $,JA2BETAVERSION;JA2TESTVERSION;DEBUG_ATTACKBUSY,>) + # Due to widespread preprocessor definition abuse in the codebase, practically # every library-language-executable combination is its own compilation target # TODO: refactor preprocessor usage onto, ideally, a single translation unit foreach(lang IN LISTS LangTargets) foreach(exe IN LISTS ApplicationTargets) - set(targPrefix ${exe}_${lang}) - - # make a copy of the library list for each language/library combination - list(SUBLIST Ja2_Libs 0 -1 ${targPrefix}_Targets) + set(Executable ${exe}_${lang}) - add_executable(${targPrefix} WIN32) - target_sources(${targPrefix} PRIVATE ${Ja2Src}) - target_link_libraries(${targPrefix} PRIVATE ${Ja2_Libraries}) + # executable for an application/language combination, e.g. JA2_ENGLISH.exe + add_executable(${Executable} WIN32) + target_sources(${Executable} PRIVATE ${Ja2Src}) - foreach(lib IN LISTS ${targPrefix}_Targets) - set(tgt ${targPrefix}_${lib}) - - add_library(${tgt}) - target_sources(${tgt} PRIVATE ${${lib}Src}) + # Good libraries have already been built, can be simply linked here + target_link_libraries(${Executable} PRIVATE ${Ja2_Libraries}) + # for each app/lang combination, the Very Bad libraries need to be built, + # with the appropriate preprocessor definitions + foreach(lib IN LISTS Ja2_Libs) + # syntactic sugar to hopefully make this more readable + set(VeryBadLib ${Executable}_${lib}) set(isEditor $) set(isUb $) set(isUbEditor $) - target_compile_definitions(${tgt} PUBLIC + # static library for an app/lang combination, e.g. JA2_ENGLISH_SGP.lib + add_library(${VeryBadLib}) + target_sources(${VeryBadLib} PRIVATE ${${lib}Src}) + + target_compile_definitions(${VeryBadLib} PUBLIC $ $ $ - $,JA2BETAVERSION;JA2TESTVERSION;DEBUG_ATTACKBUSY,> + ${debugFlags} ${lang} ) - target_link_libraries(${targPrefix} PUBLIC ${tgt}) + target_link_libraries(${Executable} PUBLIC ${VeryBadLib}) endforeach() - # SGP is the only one calling these, so they can go here - target_link_libraries(${targPrefix}_SGP PRIVATE "ddraw.lib" "${PROJECT_SOURCE_DIR}/fmodvc.lib") - target_link_libraries(${targPrefix}_SGP PUBLIC libpng) + # only SGP depends on these + target_link_libraries(${Executable}_SGP PRIVATE "ddraw.lib" "${PROJECT_SOURCE_DIR}/fmodvc.lib") + target_link_libraries(${Executable}_SGP PUBLIC libpng) endforeach() endforeach()