Use Go modules with delocate.
This makes running go test, etc., in util/fipstools/delocate work! This adds a go_executable command to CMake like: go_executable(delocate boringssl.googlesource.com/boringssl/util/fipstools/delocate) which internally gets dependencies and whatnot so it behaves like usual Go. Update-Note: delocate has been rearranged a bit. Change-Id: I244a7317dd8d4f2ab77a0daa624ed3e0b385faef Reviewed-on: https://boringssl-review.googlesource.com/31885 Commit-Queue: David Benjamin <davidben@google.com> CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org> Reviewed-by: Adam Langley <agl@google.com>
This commit is contained in:
parent
302ef5ee12
commit
5baee45652
@ -334,6 +334,43 @@ if(OPENSSL_SMALL)
|
||||
add_definitions(-DOPENSSL_SMALL)
|
||||
endif()
|
||||
|
||||
function(go_executable dest package)
|
||||
set(godeps "${CMAKE_SOURCE_DIR}/util/godeps.go")
|
||||
if(${CMAKE_VERSION} VERSION_LESS "3.7" OR
|
||||
NOT ${CMAKE_GENERATOR} STREQUAL "Ninja")
|
||||
# The DEPFILE parameter to add_custom_command is new as of CMake 3.7 and
|
||||
# only works with Ninja. Query the sources at configure time. Additionally,
|
||||
# everything depends on go.mod. That affects what external packages to use.
|
||||
execute_process(COMMAND ${GO_EXECUTABLE} run ${godeps} -format cmake
|
||||
-pkg ${package}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE sources
|
||||
RESULT_VARIABLE godeps_result)
|
||||
add_custom_command(OUTPUT ${dest}
|
||||
COMMAND ${GO_EXECUTABLE} build
|
||||
-o ${CMAKE_CURRENT_BINARY_DIR}/${dest} ${package}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
DEPENDS ${sources} ${CMAKE_SOURCE_DIR}/go.mod)
|
||||
else()
|
||||
# Ninja expects the target in the depfile to match the output. This is a
|
||||
# relative path from the build directory.
|
||||
string(LENGTH "${CMAKE_BINARY_DIR}" root_dir_length)
|
||||
math(EXPR root_dir_length "${root_dir_length} + 1")
|
||||
string(SUBSTRING "${CMAKE_CURRENT_BINARY_DIR}" ${root_dir_length} -1 target)
|
||||
set(target "${target}/${dest}")
|
||||
|
||||
set(depfile "${CMAKE_CURRENT_BINARY_DIR}/${dest}.d")
|
||||
add_custom_command(OUTPUT ${dest}
|
||||
COMMAND ${GO_EXECUTABLE} build
|
||||
-o ${CMAKE_CURRENT_BINARY_DIR}/${dest} ${package}
|
||||
COMMAND ${GO_EXECUTABLE} run ${godeps} -format depfile
|
||||
-target ${target} -pkg ${package} -out ${depfile}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
DEPENDS ${godeps} ${CMAKE_SOURCE_DIR}/go.mod
|
||||
DEPFILE ${depfile})
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# CMake's iOS support uses Apple's multiple-architecture toolchain. It takes an
|
||||
# architecture list from CMAKE_OSX_ARCHITECTURES, leaves CMAKE_SYSTEM_PROCESSOR
|
||||
# alone, and expects all architecture-specific logic to be conditioned within
|
||||
|
@ -141,21 +141,12 @@ if(FIPS_DELOCATE)
|
||||
set_target_properties(bcm_c_generated_asm PROPERTIES COMPILE_OPTIONS "-S")
|
||||
set_target_properties(bcm_c_generated_asm PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
function(prepend_path values prefix output)
|
||||
set(result)
|
||||
foreach(value ${values})
|
||||
list(APPEND result "${prefix}/${value}")
|
||||
endforeach(value)
|
||||
set(${output} ${result} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
prepend_path("${BCM_ASM_SOURCES}" "${CMAKE_CURRENT_BINARY_DIR}" DELOCATE_ASM_ARGS)
|
||||
|
||||
go_executable(delocate boringssl.googlesource.com/boringssl/util/fipstools/delocate)
|
||||
add_custom_command(
|
||||
OUTPUT bcm-delocated.S
|
||||
COMMAND ${GO_EXECUTABLE} run util/fipstools/delocate.go util/fipstools/delocate.peg.go util/fipstools/ar.go util/fipstools/const.go -a $<TARGET_FILE:bcm_c_generated_asm> -o ${CMAKE_CURRENT_BINARY_DIR}/bcm-delocated.S ${DELOCATE_ASM_ARGS}
|
||||
DEPENDS bcm_c_generated_asm ${BCM_ASM_SOURCES} ${CMAKE_SOURCE_DIR}/util/fipstools/delocate.go ${CMAKE_SOURCE_DIR}/util/fipstools/delocate.peg.go ${CMAKE_SOURCE_DIR}/util/fipstools/ar.go ${CMAKE_SOURCE_DIR}/util/fipstools/const.go
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
COMMAND ./delocate -a $<TARGET_FILE:bcm_c_generated_asm> -o bcm-delocated.S ${BCM_ASM_SOURCES}
|
||||
DEPENDS bcm_c_generated_asm delocate ${BCM_ASM_SOURCES}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
|
||||
add_library(
|
||||
@ -171,11 +162,13 @@ if(FIPS_DELOCATE)
|
||||
set_target_properties(bcm_hashunset PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
||||
set_target_properties(bcm_hashunset PROPERTIES LINKER_LANGUAGE C)
|
||||
|
||||
go_executable(inject-hash
|
||||
boringssl.googlesource.com/boringssl/util/fipstools/inject-hash)
|
||||
add_custom_command(
|
||||
OUTPUT bcm.o
|
||||
COMMAND ${GO_EXECUTABLE} run util/fipstools/inject-hash.go util/fipstools/ar.go util/fipstools/const.go -o ${CMAKE_CURRENT_BINARY_DIR}/bcm.o -in-archive $<TARGET_FILE:bcm_hashunset>
|
||||
DEPENDS bcm_hashunset ${CMAKE_SOURCE_DIR}/util/fipstools/inject-hash.go ${CMAKE_SOURCE_DIR}/util/fipstools/ar.go ${CMAKE_SOURCE_DIR}/util/fipstools/const.go
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
COMMAND ./inject-hash -o bcm.o -in-archive $<TARGET_FILE:bcm_hashunset>
|
||||
DEPENDS bcm_hashunset inject-hash
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
|
||||
# The outputs of add_custom_command cannot be referenced outside of the
|
||||
|
@ -25,6 +25,8 @@ import (
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"boringssl.googlesource.com/boringssl/util/fipstools/fipscommon"
|
||||
)
|
||||
|
||||
// inputFile represents a textual assembly file.
|
||||
@ -1405,7 +1407,7 @@ func transform(w stringWriter, inputs []inputFile) error {
|
||||
w.WriteString(".type BORINGSSL_bcm_text_hash, @object\n")
|
||||
w.WriteString(".size BORINGSSL_bcm_text_hash, 64\n")
|
||||
w.WriteString("BORINGSSL_bcm_text_hash:\n")
|
||||
for _, b := range uninitHashValue {
|
||||
for _, b := range fipscommon.UninitHashValue {
|
||||
w.WriteString(".byte 0x" + strconv.FormatUint(uint64(b), 16) + "\n")
|
||||
}
|
||||
|
||||
@ -1423,7 +1425,7 @@ func parseInputs(inputs []inputFile) error {
|
||||
}
|
||||
defer arFile.Close()
|
||||
|
||||
ar, err := ParseAR(arFile)
|
||||
ar, err := fipscommon.ParseAR(arFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
@ -14,7 +14,7 @@
|
||||
|
||||
// ar.go contains functions for parsing .a archive files.
|
||||
|
||||
package main
|
||||
package fipscommon
|
||||
|
||||
import (
|
||||
"bytes"
|
@ -12,11 +12,11 @@
|
||||
// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||||
|
||||
package main
|
||||
package fipscommon
|
||||
|
||||
// uninitHashValue is the default hash value that we inject into the module.
|
||||
// UninitHashValue is the default hash value that we inject into the module.
|
||||
// This value need only be distinct, i.e. so that we can safely
|
||||
// search-and-replace it in an object file.
|
||||
var uninitHashValue = [64]byte{
|
||||
var UninitHashValue = [64]byte{
|
||||
0xae, 0x2c, 0xea, 0x2a, 0xbd, 0xa6, 0xf3, 0xec, 0x97, 0x7f, 0x9b, 0xf6, 0x94, 0x9a, 0xfc, 0x83, 0x68, 0x27, 0xcb, 0xa0, 0xa0, 0x9f, 0x6b, 0x6f, 0xde, 0x52, 0xcd, 0xe2, 0xcd, 0xff, 0x31, 0x80, 0xa2, 0xd4, 0xc3, 0x66, 0x0f, 0xc2, 0x6a, 0x7b, 0xf4, 0xbe, 0x39, 0xa2, 0xd7, 0x25, 0xdb, 0x21, 0x98, 0xe9, 0xd5, 0x53, 0xbf, 0x5c, 0x32, 0x06, 0x83, 0x34, 0x0c, 0x65, 0x89, 0x52, 0xbd, 0x1f,
|
||||
}
|
@ -28,6 +28,8 @@ import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"boringssl.googlesource.com/boringssl/util/fipstools/fipscommon"
|
||||
)
|
||||
|
||||
func do(outPath, oInput string, arInput string) error {
|
||||
@ -43,7 +45,7 @@ func do(outPath, oInput string, arInput string) error {
|
||||
}
|
||||
defer arFile.Close()
|
||||
|
||||
ar, err := ParseAR(arFile)
|
||||
ar, err := fipscommon.ParseAR(arFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -145,12 +147,12 @@ func do(outPath, oInput string, arInput string) error {
|
||||
// Replace the default hash value in the object with the calculated
|
||||
// value and write it out.
|
||||
|
||||
offset := bytes.Index(objectBytes, uninitHashValue[:])
|
||||
offset := bytes.Index(objectBytes, fipscommon.UninitHashValue[:])
|
||||
if offset < 0 {
|
||||
return errors.New("did not find uninitialised hash value in object file")
|
||||
}
|
||||
|
||||
if bytes.Index(objectBytes[offset+1:], uninitHashValue[:]) >= 0 {
|
||||
if bytes.Index(objectBytes[offset+1:], fipscommon.UninitHashValue[:]) >= 0 {
|
||||
return errors.New("found two occurrences of uninitialised hash value in object file")
|
||||
}
|
||||
|
203
util/godeps.go
Normal file
203
util/godeps.go
Normal file
@ -0,0 +1,203 @@
|
||||
// Copyright (c) 2018, Google Inc.
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
// godeps prints out dependencies of a package in either CMake or Make depfile
|
||||
// format, for incremental rebuilds.
|
||||
//
|
||||
// The depfile format is preferred. It works correctly when new files are added.
|
||||
// However, CMake only supports depfiles for custom commands with Ninja and
|
||||
// starting CMake 3.7. For other configurations, we also support CMake's format,
|
||||
// but CMake must be rerun when file lists change.
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"go/build"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
format = flag.String("format", "cmake", "The format to output to, either 'cmake' or 'depfile'")
|
||||
mainPkg = flag.String("pkg", "", "The package to print dependencies for")
|
||||
target = flag.String("target", "", "The name of the output file")
|
||||
out = flag.String("out", "", "The path to write the output to. If unset, this is stdout")
|
||||
)
|
||||
|
||||
func cMakeQuote(in string) string {
|
||||
// See https://cmake.org/cmake/help/v3.0/manual/cmake-language.7.html#quoted-argument
|
||||
var b strings.Builder
|
||||
b.Grow(len(in))
|
||||
// Iterate over in as bytes.
|
||||
for i := 0; i < len(in); i++ {
|
||||
switch c := in[i]; c {
|
||||
case '\\', '"':
|
||||
b.WriteByte('\\')
|
||||
b.WriteByte(c)
|
||||
case '\t':
|
||||
b.WriteString("\\t")
|
||||
case '\r':
|
||||
b.WriteString("\\r")
|
||||
case '\n':
|
||||
b.WriteString("\\n")
|
||||
default:
|
||||
b.WriteByte(in[i])
|
||||
}
|
||||
}
|
||||
return b.String()
|
||||
}
|
||||
|
||||
func writeCMake(outFile *os.File, files []string) error {
|
||||
for i, file := range files {
|
||||
if i != 0 {
|
||||
if _, err := outFile.WriteString(";"); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if _, err := outFile.WriteString(cMakeQuote(file)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func makeQuote(in string) string {
|
||||
// See https://www.gnu.org/software/make/manual/make.html#Rule-Syntax
|
||||
var b strings.Builder
|
||||
b.Grow(len(in))
|
||||
// Iterate over in as bytes.
|
||||
for i := 0; i < len(in); i++ {
|
||||
switch c := in[i]; c {
|
||||
case '$':
|
||||
b.WriteString("$$")
|
||||
case '#', '\\', ' ':
|
||||
b.WriteByte('\\')
|
||||
b.WriteByte(c)
|
||||
default:
|
||||
b.WriteByte(c)
|
||||
}
|
||||
}
|
||||
return b.String()
|
||||
}
|
||||
|
||||
func writeDepfile(outFile *os.File, files []string) error {
|
||||
if _, err := fmt.Fprintf(outFile, "%s:", makeQuote(*target)); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, file := range files {
|
||||
if _, err := fmt.Fprintf(outFile, " %s", makeQuote(file)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
_, err := outFile.WriteString("\n")
|
||||
return err
|
||||
}
|
||||
|
||||
func appendPrefixed(list, newFiles []string, prefix string) []string {
|
||||
for _, file := range newFiles {
|
||||
list = append(list, filepath.Join(prefix, file))
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
|
||||
if len(*mainPkg) == 0 {
|
||||
fmt.Fprintf(os.Stderr, "-pkg argument is required.\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
var isDepfile bool
|
||||
switch *format {
|
||||
case "depfile":
|
||||
isDepfile = true
|
||||
case "cmake":
|
||||
isDepfile = false
|
||||
default:
|
||||
fmt.Fprintf(os.Stderr, "Unknown format: %q\n", *format)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if isDepfile && len(*target) == 0 {
|
||||
fmt.Fprintf(os.Stderr, "-target argument is required for depfile.\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
done := make(map[string]struct{})
|
||||
var files []string
|
||||
var recurse func(pkgName string) error
|
||||
recurse = func(pkgName string) error {
|
||||
pkg, err := build.Default.Import(pkgName, ".", 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Skip standard packages.
|
||||
if pkg.Goroot {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Skip already-visited packages.
|
||||
if _, ok := done[pkg.Dir]; ok {
|
||||
return nil
|
||||
}
|
||||
done[pkg.Dir] = struct{}{}
|
||||
|
||||
files = appendPrefixed(files, pkg.GoFiles, pkg.Dir)
|
||||
files = appendPrefixed(files, pkg.CgoFiles, pkg.Dir)
|
||||
// Include ignored Go files. A subsequent change may cause them
|
||||
// to no longer be ignored.
|
||||
files = appendPrefixed(files, pkg.IgnoredGoFiles, pkg.Dir)
|
||||
|
||||
// Recurse into imports.
|
||||
for _, importName := range pkg.Imports {
|
||||
if err := recurse(importName); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if err := recurse(*mainPkg); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error getting dependencies: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
sort.Strings(files)
|
||||
|
||||
outFile := os.Stdout
|
||||
if len(*out) != 0 {
|
||||
var err error
|
||||
outFile, err = os.Create(*out)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error writing output: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer outFile.Close()
|
||||
}
|
||||
|
||||
var err error
|
||||
if isDepfile {
|
||||
err = writeDepfile(outFile, files)
|
||||
} else {
|
||||
err = writeCMake(outFile, files)
|
||||
}
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error writing output: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user