1 # Copyright 2014 The Chromium Authors. All rights reserved. 2 # Use of this source code is governed by a BSD-style license that can be 3 # found in the LICENSE file. 4 5 # This provides the yasm_assemble() template which uses YASM to assemble 6 # assembly files. 7 # 8 # Files to be assembled with YASM should have an extension of .asm. 9 # 10 # Parameters 11 # 12 # yasm_flags (optional) 13 # [list of strings] Pass additional flags into YASM. These are appended 14 # to the command line. Note that the target machine type and system is 15 # already set up based on the current toolchain so you don't need to 16 # specify these things (see below). 17 # 18 # Example: yasm_flags = [ "--force-strict" ] 19 # 20 # include_dirs (optional) 21 # [list of dir names] List of additional include dirs. Note that the 22 # source root and the root generated file dir is always added, just like 23 # our C++ build sets up. 24 # 25 # Example: include_dirs = [ "//some/other/path", target_gen_dir ] 26 # 27 # defines (optional) 28 # [list of strings] List of defines, as with the native code defines. 29 # 30 # Example: defines = [ "FOO", "BAR=1" ] 31 # 32 # source_prereqs, deps, visibility (optional) 33 # These have the same meaning as in an action. 34 # 35 # Example 36 # 37 # yasm_assemble("my_yasm_target") { 38 # sources = [ 39 # "ultra_optimized_awesome.asm", 40 # ] 41 # include_dirs = [ "assembly_include" ] 42 # } 43 44 if (is_mac || is_ios) { 45 if (cpu_arch == "x86") { 46 _yasm_flags = [ 47 "-fmacho32", 48 "-m", "x86", 49 ] 50 } else if (cpu_arch == "x64") { 51 _yasm_flags = [ 52 "-fmacho64", 53 "-m", "amd64", 54 ] 55 } 56 } else if (is_posix) { 57 if (cpu_arch == "x86") { 58 _yasm_flags = [ 59 "-felf32", 60 "-m", "x86", 61 ] 62 } else if (cpu_arch == "x64") { 63 _yasm_flags = [ 64 "-DPIC", 65 "-felf64", 66 "-m", "amd64", 67 ] 68 } 69 } else if (is_win) { 70 if (cpu_arch == "x86") { 71 _yasm_flags = [ 72 "-DPREFIX", 73 "-fwin32", 74 "-m", "x86", 75 ] 76 } else if (cpu_arch == "x64") { 77 _yasm_flags = [ 78 "-fwin64", 79 "-m", "amd64", 80 ] 81 } 82 } 83 84 # Default yasm include dirs. Make it match the native build (source root and 85 # root generated code directory). 86 _yasm_flags += [ 87 # Using "//." will produce a relative path "../.." which looks better than 88 # "../../" which will result from using "//" as the base (although both 89 # work). This is because rebase_path will terminate the result in a slash if 90 # the input ends in a slash. 91 "-I" + rebase_path("//.", root_build_dir), 92 "-I" + rebase_path(root_gen_dir, root_build_dir), 93 ] 94 95 if (is_win) { 96 asm_obj_extension = "obj" 97 } else { 98 asm_obj_extension = "o" 99 } 100 101 template("yasm_assemble") { 102 # TODO(ajwong): Support use_system_yasm. 103 assert(defined(invoker.sources), "Need sources defined for $target_name") 104 105 # Only depend on YASM on x86 systems. Force compilation of .asm files for 106 # ARM to fail. 107 assert(cpu_arch == "x86" || cpu_arch == "x64") 108 109 action_name = "${target_name}_action" 110 source_set_name = target_name 111 112 action_foreach(action_name) { 113 visibility = ":$source_set_name" # Only the source set can depend on this. 114 115 script = "//third_party/yasm/run_yasm.py" 116 sources = invoker.sources 117 118 if (defined(invoker.source_prereqs)) { 119 source_prereqs = invoker.source_prereqs 120 } 121 122 # Executable (first in the args). The binary might be in the root build dir 123 # (no cross-compiling) or in a toolchain-specific subdirectory of that 124 # (when cross-compiling). 125 yasm_label = "//third_party/yasm($host_toolchain)" 126 args = [ "./" + # Force current dir. 127 rebase_path(get_label_info(yasm_label, "root_out_dir") + "/yasm", 128 root_build_dir) 129 ] 130 131 # Deps. 132 deps = [ yasm_label ] 133 if (defined(invoker.deps)) { 134 deps += invoker.deps 135 } 136 137 # Flags. 138 args += _yasm_flags 139 if (defined(invoker.yasm_flags)) { 140 args += invoker.yasm_flags 141 } 142 143 # Extra include directories. 144 if (defined(invoker.include_dirs)) { 145 foreach(include, invoker.include_dirs) { 146 args += [ "-I" + rebase_path(include, root_build_dir) ] 147 } 148 } 149 150 # Extra defines. 151 if (defined(invoker.defines)) { 152 foreach(def, invoker.defines) { 153 args += [ "-D$def" ] 154 } 155 } 156 157 # Output file. 158 # 159 # TODO(brettw) it might be nice if there was a source expansion for the 160 # path of the source file relative to the source root. Then we could 161 # exactly duplicate the naming and location of object files from the 162 # native build, which would be: 163 # "$root_out_dir/${target_name}.{{source_dir_part}}.$asm_obj_extension" 164 outputs = [ "$target_out_dir/{{source_name_part}}.o" ] 165 args += [ 166 "-o", rebase_path(outputs[0], root_build_dir), 167 "{{source}}" 168 ] 169 170 # The wrapper script run_yasm will write the depfile to the same name as 171 # the output but with .d appended (like gcc will). 172 depfile = outputs[0] + ".d" 173 } 174 175 # Gather the .o files into a linkable thing. This doesn't actually link 176 # anything (a source set just compiles files to link later), but will pass 177 # the object files generated by the action up the dependency chain. 178 source_set(source_set_name) { 179 if (defined(invoker.visibility)) { 180 visibility = invoker.visibility 181 } 182 183 sources = get_target_outputs(":$action_name") 184 } 185 } 186