load(moc) load(resources) defineReplace(getTargetType) { equals(TEMPLATE, "app"):return("executable") equals(TEMPLATE, "lib") { CONFIG(static): return("static_library") return("shared_library") } return("none") } defineReplace(filter_flag_values) { value_to_check = $$1 macos:equals(value_to_check, "$(EXPORT_ARCH_ARGS)") { # EXPORT_ARCH_ARGS comes from qtbase/mkspecs/features/mac/default_post.prf which is a way # to figure out the architectures to pass to the compiler at Makefile time. Because this # variable expansion is not supported by GN, we filter it out. GN takes care of assigning # the architecture itself. return("") } return($$value_to_check) } isEmpty(GN_FILE): GN_FILE = $$system_path($$_PRO_FILE_PWD_/BUILD.gn) isEmpty(GN_RUN_BINARY_SCRIPT): GN_RUN_BINARY_SCRIPT = "//build/gn_run_binary.py" isEmpty(GN_FIND_MOCABLES_SCRIPT): GN_FIND_MOCABLES_SCRIPT = "//build/gn_find_mocables.py" # MOC SETUP GN_CONTENTS += "moc_source_h_files = exec_script(\"$$GN_FIND_MOCABLES_SCRIPT\"," GN_CONTENTS += " [" for (headerfile, HEADERS): GN_CONTENTS += " \"$$GN_SRC_DIR/$$headerfile\"," GN_CONTENTS += " ], \"list lines\", [\"$$system_path($$_PRO_FILE_)\"]"\ ")" GN_CONTENTS += "moc_source_cpp_files = exec_script(\"$$GN_FIND_MOCABLES_SCRIPT\"," GN_CONTENTS += " [" for (sourcefile, SOURCES): GN_CONTENTS += " \"$$GN_SRC_DIR/$$sourcefile\"," GN_CONTENTS += " ], \"list lines\", [\"$$system_path($$_PRO_FILE_)\"]"\ ")" DEFINES_LIST = $$join(DEFINES, " -D", "-D") INCLUDE_LIST = $$join(INCLUDEPATH, " -I", "-I") # we don't generate a moc_predef file yet. MOC_PREDEF_FILE = MOC_COMMAND = $$clean_path($$mocCmdBase()) MOC_COMMAND = $$replace(MOC_COMMAND, $$re_escape("$(DEFINES)"), $$DEFINES_LIST) MOC_COMMAND = $$replace(MOC_COMMAND, $$re_escape("$(INCPATH)"), $$INCLUDE_LIST) MOC_COMMAND = $$eval($$list($$MOC_COMMAND)) GN_CONTENTS += "if (moc_source_h_files != []) {" GN_CONTENTS += " action_foreach(\"generate_h_mocs\") {"\ " script = \"$$GN_RUN_BINARY_SCRIPT\"" GN_CONTENTS += " sources = moc_source_h_files" \ " outputs = [ \"$target_gen_dir/.moc/moc_{{source_name_part}}.cpp\" ]" GN_CONTENTS += " inputs = [ \"$$system_path($$_PRO_FILE_)\" ]" \ " args = [" for(token, MOC_COMMAND): GN_CONTENTS += " \"$$replace(token,\",\\\")\"," GN_CONTENTS += " \"{{source}}\"," \ " \"-o\"," \ " rebase_path(\"$target_gen_dir/.moc/moc_{{source_name_part}}.cpp\")"\ " ]" GN_CONTENTS += " }" GN_CONTENTS += "}" GN_CONTENTS += "if (moc_source_cpp_files != []) {" GN_CONTENTS += " action_foreach(\"generate_cpp_mocs\") {"\ " script = \"$$GN_RUN_BINARY_SCRIPT\"" GN_CONTENTS += " sources = moc_source_cpp_files" \ " outputs = [ \"$target_gen_dir/.moc/{{source_name_part}}.moc\" ]" GN_CONTENTS += " inputs = [ \"$$system_path($$_PRO_FILE_)\" ]" \ " args = [" for(token, MOC_COMMAND): GN_CONTENTS += " \"$$replace(token,\",\\\")\"," GN_CONTENTS += " \"{{source}}\"," \ " \"-o\"," \ " rebase_path(\"$target_gen_dir/.moc/{{source_name_part}}.moc\")"\ " ]" GN_CONTENTS += " }" GN_CONTENTS += "}" # RESOURCES SETUP CLEAN_QMAKE_RCC = $$clean_path($$QMAKE_RCC) !isEmpty(RESOURCES) { GN_CONTENTS += "action_foreach(\"generate_resources\") {"\ " script = \"$$GN_RUN_BINARY_SCRIPT\"" GN_CONTENTS += " sources = [" for (sourcefile, RESOURCES): GN_CONTENTS += " \"$$GN_SRC_DIR/$$sourcefile\"," GN_CONTENTS += " ]" \ " outputs = [ \"$target_gen_dir/.rcc/qrc_{{source_name_part}}.cpp\" ]" GN_CONTENTS += " inputs = [ \"$$system_path($$_PRO_FILE_)\" ]" \ " args = [" \ " \"$$replace(CLEAN_QMAKE_RCC,\",\\\")\"," for(resource_flag, $$QMAKE_RESOURCE_FLAGS): GN_CONTENTS += " \"$$resource_flag\"" GN_CONTENTS += " \"-name\"," \ " \"{{source_name_part}}\"," \ " \"{{source}}\"," \ " \"-o\"," \ " rebase_path(\"$target_gen_dir/.rcc/qrc_{{source_name_part}}.cpp\")"\ " ]" GN_CONTENTS += "}" } # CONFIG SETUP GN_CONTENTS += "config(\"$${TARGET}_config\") {" !isEmpty(QMAKE_CFLAGS) { GN_CONTENTS += " cflags = [" for(flag, QMAKE_CFLAGS): GN_CONTENTS += " \"$$filter_flag_values($$flag)\"," GN_CONTENTS += " ]" } !isEmpty(QMAKE_FRAMEWORKPATH) { GN_CONTENTS += " cflags += [" for(path, QMAKE_FRAMEWORKPATH): GN_CONTENTS += " \"-F$$path\"," GN_CONTENTS += " ]" } # Stop the barrage of unused variables warnings. gcc|clang { QMAKE_CXXFLAGS += "-Wno-unused-parameter" QMAKE_CXXFLAGS += "-Wno-unused-variable" } else:msvc { QMAKE_CXXFLAGS += /wd4100 /wd4101 } !isEmpty(QMAKE_CXXFLAGS) { GN_CONTENTS += " cflags_cc = [" for(flag, QMAKE_CXXFLAGS): GN_CONTENTS += " \"$$filter_flag_values($$flag)\"," GN_CONTENTS += " ]" } GN_CONTENTS += " defines = [" # Remove single quotes around function macro defines, so that GN doesn't escape them, thus breaking # the macro. # Also add a layer of escaping for double quotes. for (define, DEFINES): { define = $$replace(define,\",\\\") define = $$replace(define,\',) GN_CONTENTS += " \"$$define\"," } GN_CONTENTS += " ]" GN_CONTENTS += " include_dirs = [" for (path, INCLUDEPATH): GN_CONTENTS += " \"$$path\"," GN_CONTENTS += " rebase_path(\"$target_gen_dir/.moc/\")," GN_CONTENTS += " \"$$QMAKESPEC\"" GN_CONTENTS += " ]" GN_CONTENTS += " ldflags = [" for (flag, QMAKE_LFLAGS): GN_CONTENTS += " \"$$filter_flag_values($$flag)\"," for (flag, GN_FLAGS): GN_CONTENTS += " \"$$flag\"," !isEmpty(QMAKE_RPATHDIR) { for (rpath, QMAKE_RPATHDIR) { unix:!macos: GN_CONTENTS += " \"-Wl,-rpath=$${rpath}\"," } } !isEmpty(QMAKE_RPATHLINKDIR): GN_CONTENTS += " \"-Wl,-rpath-link=$${QMAKE_RPATHLINKDIR}\"," GN_CONTENTS += " ]" GN_CONTENTS += " lib_dirs = [" lib_dirs = $$find(LIBS, ^-L.*) lib_dirs = $$unique(lib_dirs) for (lib_dir, lib_dirs): GN_CONTENTS += " \"$$replace(lib_dir, -L, )\"," GN_CONTENTS += " ]" GN_CONTENTS += "}" # TARGET SETUP TARGET_TYPE = $$getTargetType() GN_CONTENTS += "$${TARGET_TYPE}(\"$$TARGET\") {" !isEmpty(GN_CREATE_PRI): GN_CONTENTS += " create_pri_file = $$GN_CREATE_PRI" !isEmpty(GN_IMPORTS) { for (imp, GN_IMPORTS): GN_CONTENTS += " import(\"$$imp\")" } GN_CONTENTS += " configs += [ \":$${TARGET}_config\" ] " # Source files to compile GN_CONTENTS += " sources = [" for (sourcefile, SOURCES): GN_CONTENTS += " \"$$GN_SRC_DIR/$$sourcefile\"," for (headerfile, HEADERS): GN_CONTENTS += " \"$$GN_SRC_DIR/$$headerfile\"," GN_CONTENTS += " ]" # Add Sources generated by rcc from qrc files. !isEmpty(RESOURCES): GN_CONTENTS += " sources += get_target_outputs(\":generate_resources\")" GN_CONTENTS += " if (!defined(libs)) {"\ " libs = []"\ " }" GN_CONTENTS += " libs += [" for (lib, GN_LIBS): GN_CONTENTS += " \"$$lib\"," libs = $$find(LIBS, ^-l.*) libs = $$unique(libs) for (lib, libs): GN_CONTENTS += " \"$$replace(lib, -l, )\"," GN_CONTENTS += " ]" GN_CONTENTS += " if (!defined(deps)) {"\ " deps = []"\ " }" !isEmpty(RESOURCES) { GN_CONTENTS += " deps += [" GN_CONTENTS += " \":generate_resources\"," GN_CONTENTS += " ]" } # Remove the default no_rtti config for our own cpp files, thus leaving the decision # to the compiler's defaults. This is consistent with how qtbase does it. # Unless the user explicitly configured Qt with a different RTTI setting. # Windows only for now, because macOS (and presumably Linux) does not support # partial rtti info (e.g. rtti info present for derived class, but not base class), and the # qtbase rtti feature affects only Windows. win32 { GN_CONTENTS += " configs -= [\"//build/config/compiler:no_rtti\"]" CONFIG(rtti_off): GN_CONTENTS += " configs += [\"//build/config/compiler:no_rtti\"]" CONFIG(rtti): GN_CONTENTS += " configs += [\"//build/config/compiler:rtti\"]" } GN_CONTENTS += " if (moc_source_h_files != []) {" GN_CONTENTS += " deps += [" GN_CONTENTS += " \":generate_h_mocs\"," GN_CONTENTS += " ]" # Add moc output files to compile GN_CONTENTS += " sources += get_target_outputs(\":generate_h_mocs\")" GN_CONTENTS += " }" GN_CONTENTS += " if (moc_source_cpp_files != []) {" GN_CONTENTS += " deps += [" GN_CONTENTS += " \":generate_cpp_mocs\"," GN_CONTENTS += " ]" GN_CONTENTS += " }" GN_CONTENTS += "}" GN_CONTENTS += "" GN_CONTENTS += "if (!defined(core_include_dirs)) {"\ " core_include_dirs = []"\ "}" !isEmpty(GN_CORE_INCLUDE_DIRS) { GN_CONTENTS += "core_include_dirs += [" for (inc, GN_CORE_INCLUDE_DIRS): GN_CONTENTS += " \"$$inc\"," GN_CONTENTS += "]" } !isEmpty(GN_INCLUDES) { for (inc, GN_INCLUDES): GN_CONTENTS += $$cat($$inc,lines) } build_pass|!debug_and_release: write_file($$GN_FILE, GN_CONTENTS) # The generated Makefile shouldn't build anything by itself, just re-run qmake if necessary TEMPLATE = aux SOURCES = HEADERS = RESOURCES = QMAKE_DISTCLEAN += $$GN_FILE